﻿using Entities;
using Entities.CoinEntities;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CoinModels
{
    public class CoinType
    {
        public int ID { get; set; }

        public string PrimaryCode { get; set; }

        public string SecondaryCode { get; set; }

        public DateTime DateSeen { get; set; }

        /// <summary>
        /// Persists a list of CoinTypes
        /// </summary>
        /// <param name="coinsToGrab">List To Persist</param>
        public static void SaveCoinTypes(List<CoinType> coinsToGrab)
        {
            List<CoinTypeEntity> entities = new List<CoinTypeEntity>();

            foreach(CoinType model in coinsToGrab)
            {
                entities.Add(CoinType.ConvertToEntity(model));
            }

            using (AegirContext db = new AegirContext())
            {
                foreach (CoinTypeEntity entity in entities)
                {
                    db.Coin_Type.Add(entity);
                }
                db.SaveChanges();
            }
        }

        /// <summary>
        /// Converts a cointype model to an entity for saving
        /// </summary>
        /// <param name="model">Model to convert</param>
        /// <returns>Entity for saving</returns>
        private static CoinTypeEntity ConvertToEntity(CoinType model)
        {
            CoinTypeEntity entity = new CoinTypeEntity();

            entity.id = model.ID;
            entity.primarycode = model.PrimaryCode;
            entity.secondarycode = model.SecondaryCode;
            entity.dateseen = model.DateSeen;

            return entity;
        }

        /// <summary>
        /// Gets a list of primary/secondary names of all Cryptsy coins stored
        /// </summary>
        /// <returns>List of primary/secondary names of all Cryptsy coins stored</returns>
        public static List<CoinType> GetAllCryptsyCoins()
        {
            List<CoinType> coinsToGrab = new List<CoinType>();
            List<string> primarycodes, secondarycodes;
            List<DateTime> lastseen;

            using (AegirContext db = new AegirContext())
            {
                primarycodes = db.Cryptsy_Coin.Select(cryc => cryc.primarycode).ToList<string>();
                secondarycodes = db.Cryptsy_Coin.Select(cryc => cryc.secondarycode).ToList<string>();
                lastseen = db.Cryptsy_Coin.Select(cryc => cryc.updatedat).ToList<DateTime>();
            }

            for (int i = 0; i < primarycodes.Count; i++)
            {
                CoinType coin = new CoinType();
                coin.PrimaryCode = primarycodes[i];
                coin.SecondaryCode = secondarycodes[i];
                coin.DateSeen = lastseen[i];

                CoinType possibleCoin = coinsToGrab
                    .Where(c => c.PrimaryCode == coin.PrimaryCode && c.SecondaryCode == coin.SecondaryCode).FirstOrDefault();

                if (!coinsToGrab.Contains(coin))
                {
                    coinsToGrab.Add(coin);
                }
                else if (possibleCoin.DateSeen < coin.DateSeen)
                {
                    coinsToGrab.Remove(possibleCoin);
                    coinsToGrab.Add(possibleCoin);
                }
            }

            return coinsToGrab;
        }

        /// <summary>
        /// Gets a list of primary/secondary names of all BTCe coins stored
        /// </summary>
        /// <returns>List of primary/secondary names of all BTCe coins stored</returns>
        public static List<CoinType> GetAllBTCeCoins()
        {
            List<CoinType> coinsToGrab = new List<CoinType>();
            List<string> primarycodes, secondarycodes;
            List<DateTime> lastseen;

            using (AegirContext db = new AegirContext())
            {
                primarycodes = db.BTCe_Coin.Select(btcc => btcc.primarycode).ToList<string>();
                secondarycodes = db.BTCe_Coin.Select(btcc => btcc.secondarycode).ToList<string>();
                lastseen = db.BTCe_Coin.Select(btcc => btcc.updatedat ?? DateTime.Now).ToList<DateTime>();
            }

            for (int i = 0; i < primarycodes.Count; i++)
            {
                CoinType coin = new CoinType();
                coin.PrimaryCode = primarycodes[i];
                coin.SecondaryCode = secondarycodes[i];
                coin.DateSeen = lastseen[i];

                CoinType possibleCoin = coinsToGrab
                    .Where(c => c.PrimaryCode == coin.PrimaryCode && c.SecondaryCode == coin.SecondaryCode).FirstOrDefault();

                if (!coinsToGrab.Contains(coin))
                {
                    coinsToGrab.Add(coin);
                }
                else if (possibleCoin.DateSeen < coin.DateSeen)
                {
                    coinsToGrab.Remove(possibleCoin);
                    coinsToGrab.Add(possibleCoin);
                }
            }

            return coinsToGrab;
        }

        /// <summary>
        /// Gets all currently stored coin types
        /// </summary>
        /// <returns>List of currently stored coin types</returns>
        public static List<CoinType> GetAllCoinTypes()
        {
            List<CoinType> allCoinTypes = new List<CoinType>();
            List<CoinType> currentCoinTypes = new List<CoinType>();

            // Get BTCeCoinTypes
            currentCoinTypes = GetAllBTCeCoins();
            foreach (CoinType current in currentCoinTypes)
            {
                if (!allCoinTypes.Contains(current))
                {
                    allCoinTypes.Add(current);
                }
            }

            // Get CryptsyCoinTypes
            currentCoinTypes = GetAllCryptsyCoins();
            foreach (CoinType current in currentCoinTypes)
            {
                if (!allCoinTypes.Contains(current))
                {
                    allCoinTypes.Add(current);
                }
            }

            return allCoinTypes;
        }
    }
}
